package com.rongkang.interview.juc.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @Description:
 * @author: 荣康
 * @date: 2021/12/2
 */
public class ABADemo {
    //最开始为100，版本号为1
    static AtomicReference<Integer> reference = new AtomicReference<>(100);
    static AtomicStampedReference<Integer> stampedReference = new AtomicStampedReference<>(100, 1);

    public static void main(String[] args) {

        System.out.println("===================以下是ABA问题的产生=======================");
        new Thread(() -> {
            reference.compareAndSet(100, 101);
            reference.compareAndSet(101, 100);
        }, "t1").start();
        new Thread(() -> {
            //等待一下，让上面的活干完
            try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println(reference.compareAndSet(100, 200) + " \t" + reference.get());
        }, "t2").start();
        //睡两秒等待他干完活
        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("===================以下是ABA问题的解决=========================");
        new Thread(() -> {
            int temp = stampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() +"\t 版本号为" + temp);
            //等待t4
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            stampedReference.compareAndSet(100, 101, stampedReference.getStamp(), stampedReference.getStamp() + 1);
            System.out.println("第一次修改版本号为 ：" + stampedReference.getStamp());
            stampedReference.compareAndSet(101, 100, stampedReference.getStamp(), stampedReference.getStamp() + 1);
            System.out.println("第二次修改版本号为 ：" + stampedReference.getStamp());
        }, "t3").start();

        new Thread(() -> {
            int temp = stampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() +"\t 版本号为" + temp);
            //等待t4
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            boolean b = stampedReference.compareAndSet(100, 2000, temp, temp + 1);
            System.out.println("修改成功否 ：" + b + "当前实际版本号" + stampedReference.getStamp());
            System.out.println("实际最新值 \t " + stampedReference.getReference());

        }, "t4").start();
    }
}
